
<template>
  <div class="relative">
    <div ref="container" class="three-container"></div>
    <div class="absolute top-4 left-4 space-x-2">
      <v-btn
        size="x-small"
        elevation="0"
        rounded="xl"
        class="bg-black"
        @click="toggleHelper"
      >
        {{ isHelper ? "关闭坐标辅助线" : "开启坐标辅助线" }}
      </v-btn>
      <v-btn
        size="x-small"
        elevation="0"
        rounded="xl"
        class="bg-black"
        @click="toggleAutoRotate"
      >
        {{ isAutoRotate ? "停止自动旋转" : "开启自动旋转" }}
      </v-btn>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';

// Props
const props = defineProps({
  width: { type: Number, default: 912 },
  height: { type: Number, default: 500 },
  modelPath: { type: String, required: true }
});

// Refs
const container = ref(null);
const isHelper = ref(false);
const isAutoRotate = ref(false);

// Three.js instances
let scene, camera, renderer, controls, axesHelper;
let animationFrameId = null;

// Initialize Three.js scene
const initScene = () => {
  scene = new THREE.Scene();

  // Camera setup
  camera = new THREE.PerspectiveCamera(30, props.width / props.height, 1, 3000);
  camera.position.set(150, 300, 200);
  camera.lookAt(0, 0, 0);

  // Renderer setup
  renderer = new THREE.WebGLRenderer({
    antialias: true,
    alpha: true,
    precision: 'mediump'
  });
  renderer.setSize(props.width, props.height);
  renderer.setClearColor(0xffffff);
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.outputEncoding = THREE.sRGBEncoding;

  // Light setup
  const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
  directionalLight.position.set(50, 100, -100);
  scene.add(directionalLight);

  const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
  scene.add(ambientLight);

  // Controls setup
  controls = new OrbitControls(camera, renderer.domElement);
  controls.target.set(0, 0, 0);

  // Axes helper setup
  axesHelper = new THREE.AxesHelper(100);

  // Add renderer to DOM
  container.value.appendChild(renderer.domElement);
};

// Animation loop
const animate = () => {
  if (controls.autoRotate) {
    controls.update();
  }
  renderer.render(scene, camera);
  animationFrameId = requestAnimationFrame(animate);
};

// Calculate center of model
const calculateModelCenter = (model) => {
  const box = new THREE.Box3().setFromObject(model);
  const center = new THREE.Vector3();
  box.getCenter(center);
  return center;
};

// Load GLB model
const loadModel = async () => {
  try {
    // Initialize GLTF loader
    const loader = new GLTFLoader();

    // Optional: Setup Draco decoder for compressed models
    const dracoLoader = new DRACOLoader();
    dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.5.6/');
    loader.setDRACOLoader(dracoLoader);

    const gltf = await loader.loadAsync(props.modelPath);
    const model = gltf.scene;

    // Adjust model scale if needed
    model.scale.set(1, 1, 1);
    model.position.set(0, 0, 0);
    scene.add(model);

    // Set rotation center to model's center
    const modelCenter = calculateModelCenter(model);
    controls.target.copy(modelCenter);

    // Reset camera position after model load
    camera.position.set(800, 0, 400);
    camera.lookAt(0, 0, 0);

    // Optional: Auto-adjust camera position based on model size
    const box = new THREE.Box3().setFromObject(model);
    const size = box.getSize(new THREE.Vector3());
    const maxDim = Math.max(size.x, size.y, size.z);
    camera.position.set(maxDim * 2, maxDim, maxDim);

    // Optional: Handle animations if present
    if (gltf.animations && gltf.animations.length > 0) {
      const mixer = new THREE.AnimationMixer(model);
      const action = mixer.clipAction(gltf.animations[0]);
      action.play();
    }
  } catch (error) {
    console.error('Error loading model:', error);
  }
};

// Control functions
const toggleHelper = () => {
  isHelper.value = !isHelper.value;
  if (isHelper.value) {
    scene.add(axesHelper);
  } else {
    scene.remove(axesHelper);
  }
};

const toggleAutoRotate = () => {
  isAutoRotate.value = !isAutoRotate.value;
  controls.autoRotate = isAutoRotate.value;
};

// Lifecycle hooks
onMounted(async () => {
  console.log('Model path:', props.modelPath);

  initScene();
  await loadModel();
  animate();

  // Set initial states
  isAutoRotate.value = true;
  controls.autoRotate = true;
});

onBeforeUnmount(() => {
  if (animationFrameId) {
    cancelAnimationFrame(animationFrameId);
  }

  // Cleanup Three.js resources
  renderer?.dispose();
  scene?.traverse((object) => {
    if (object instanceof THREE.Mesh) {
      object.geometry?.dispose();
      object.material?.dispose();
    }
  });
});
</script>

<style scoped>
.three-container {
  width: 100%;
  height: 100%;
  background-color: transparent;
}
</style>
